#include "be_alloc.h"
#include "cd_int.h"
#include "cd_object.h"
#include "cd_stack.h"
#include "cd_function.h"
#include "cd_inner_type.h"
#include "cd_io.h"


CD_NAMESPACE_BEGIN


class	c_int_def:public	c_entity{
public:
	virtual	c_object*	type(){
		return	inner_type(INNER_TYPE_TYPE);
	}

	virtual	const s8*	type_name(){
		return	type()->type_name();
	}
private:

};

static	c_int_def	g_int_def;
static	c_object	g_int_def_obj=c_object(&g_int_def,
					c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_adde(c_int::i_adde);
static	c_object		g_int_adde_obj=c_object(&g_int_adde,
						c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_add(c_int::i_add);
static	c_object		g_int_add_obj=c_object(&g_int_add,
						c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_sube(c_int::i_sube);
static	c_object		g_int_sube_obj=c_object(&g_int_sube,
						c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_sub(c_int::i_sub);
static	c_object		g_int_sub_obj=c_object(&g_int_sub,
						c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_mute(c_int::i_mute);
static	c_object		g_int_mute_obj=c_object(&g_int_mute,
						c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_mut(c_int::i_mut);
static	c_object		g_int_mut_obj=c_object(&g_int_mut,
						c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_dive(c_int::i_dive);
static	c_object		g_int_dive_obj=c_object(&g_int_dive,
						c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_div(c_int::i_div);
static	c_object		g_int_div_obj=c_object(&g_int_div,
						c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_mode(c_int::i_mode);
static	c_object		g_int_mode_obj=c_object(&g_int_mode,
						c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_mod(c_int::i_mod);
static	c_object		g_int_mod_obj=c_object(&g_int_mod,
						c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_neq(c_int::i_neq);
static	c_object		g_int_neq_obj=c_object(&g_int_neq,
						c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_eql(c_int::i_eql);
static	c_object		g_int_eql_obj=c_object(&g_int_eql,
						c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_lag(c_int::i_lag);
static	c_object		g_int_lag_obj=c_object(&g_int_lag,
						c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_sml(c_int::i_sml);
static	c_object		g_int_sml_obj=c_object(&g_int_sml,
						c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_lge(c_int::i_lge);
static	c_object		g_int_lge_obj=c_object(&g_int_lge,
						c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_sme(c_int::i_sme);
static	c_object		g_int_sme_obj=c_object(&g_int_sme,
						c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_hsh(c_int::i_hash);
static	c_object		g_int_hsh_obj=c_object(&g_int_hsh,
						c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_inc(c_int::i_inc);
static	c_object		g_int_inc_obj=c_object(&g_int_inc,
						c_object::OBJ_TYPE_CONST);
static	c_function_i	g_int_dec(c_int::i_dec);
static	c_object		g_int_dec_obj=c_object(&g_int_dec,
						c_object::OBJ_TYPE_CONST);

const	s8*	c_int::type_name(	)
{
	return	"int";
}

c_object*	c_int::type(	)
{
	return	&g_int_def_obj;
}

c_object*	c_int::get_member(const s8* name)
{
	c_object*	ret	=	NULL;
	switch(name[1]){
	case	'=':	
		switch(name[2]){
		case	'\0':
			switch(name[0]){
			case	'+':
				return	&g_int_adde_obj;
			case	'-':
				return	&g_int_sube_obj;
			case	'*':
				return	&g_int_mute_obj;
			case	'/':
				return	&g_int_dive_obj;
			case	'%':
				return	&g_int_mode_obj;
			case	'=':
				return	&g_int_eql_obj;
			case	'!':
				return	&g_int_neq_obj;
			case	'>':
				return	&g_int_lge_obj;
			case	'<':
				return	&g_int_sme_obj;
			}
			break;
		}
		break;
	case	'\0':
			switch(name[0]){
			case	'+':
				return	&g_int_add_obj;
			case	'-':
				return	&g_int_sub_obj;
			case	'*':
				return	&g_int_mut_obj;
			case	'/':
				return	&g_int_div_obj;
			case	'%':
				return	&g_int_mod_obj;
			}
			break;
	case	'+':
		if(name[0]	==	'+')
			return	&g_int_inc_obj;
	case	'-':
		if(name[0]	==	'-')
			return	&g_int_dec_obj;
		break;
	case	'a':
		if(name[0]	==	'h'	
			&&	name[2]	==	's'
			&&	name[3]	==	'h')
			return	&g_int_hsh_obj;
		break;
	}

	return	ret;
}

c_object*	c_int::get_member(s32 index)
{
	c_object*	ret	=	NULL;
	switch(index){
	case	0:
		return	&g_int_adde_obj;
	case	1:
		return	&g_int_add_obj;
	case	2:
		return	&g_int_sube_obj;
	case	3:
		return	&g_int_sub_obj;
	case	4:
		return	&g_int_mute_obj;
	case	5:
		return	&g_int_mut_obj;
	case	6:
		return	&g_int_dive_obj;
	case	7:
		return	&g_int_div_obj;
	case	8:
		return	&g_int_mode_obj;
	case	9:
		return	&g_int_mod_obj;
	case	10:
		return	&g_int_neq_obj;
	case	11:
		return	&g_int_eql_obj;
	case	12:
		return	&g_int_lag_obj;
	case	13:
		return	&g_int_sml_obj;
	case	14:
		return	&g_int_lge_obj;
	case	15:
		return	&g_int_sme_obj;
	case	16:
		return	&g_int_inc_obj;
	case	17:
		return	&g_int_dec_obj;
	case	18:
		return	&g_int_hsh_obj;
	}
	return	ret;
}

c_int&	c_int::operator+=	(const	c_int&	r)
{
	m_val	+=	r.m_val;
	return	*this;
}

c_int	operator+(const	c_int&	l,	const	c_int&	r)
{
	c_int	ret;
	ret.m_val	=	l.m_val	+	r.m_val;
	return	ret;
}

c_entity*	c_int::clone(c_stack* stack)
{
	c_int*	p	=	(c_int*)stack->allocate(sizeof(c_int));
	return	::new(p)	c_int(m_val);
}

static	inline	s32	i_stack_get(c_stack*	stack,	
	c_int*&	ts,	c_int*&	i)
{
	s32			ret	=	en_sucess;
	c_object*	ol	=	stack->get_ths_reg();
	assert(ol);
	ts	=	(c_int*)ol->entity();
	c_object*	or	=	stack->argu(0);
	if(!or){
		stack->throw_exception(EXCP_INVALID_ADDR);
		return	en_invalid_addr;
	}
	c_entity*	ent	=	or->entity();
	if(!ent){
		stack->throw_exception(EXCP_NULL_ARGU);
		return	en_null_argu;	
	}
	i	=	dynamic_cast<c_int*>(ent);
	if(!i){
		stack->throw_exception(EXCP_INVALID_OP_TYPE);
		return	en_invalid_type;			
	}
	return	ret;
}

static	inline	s32	i_stack_get(c_stack*	stack,	
	c_int*&	ts)
{
	s32			ret	=	en_sucess;
	c_object*	ol	=	stack->get_ths_reg();
	assert(ol);
	ts	=	(c_int*)ol->entity();
	return	ret;
}

s32	c_int::i_adde(c_stack*	stack)
{
	int			ret	=	en_sucess;
	c_int*		ts	=	NULL;
	c_int*		i	=	NULL;
	ret	=	i_stack_get(stack,	ts,	i);
	if(ret	<	0){
		return	ret;
	}
	ts->m_val	+=	i->m_val;
	stack->set_ireg(ts->m_val);
	return	ret;
}

s32	c_int::i_add(c_stack*	stack)
{
	s32			ret	=	en_sucess;
	c_int*		ts	=	NULL;
	c_int*		i	=	NULL;
	c_object*	ir	=	stack->get_ret_reg();
	ret	=	i_stack_get(stack,	ts,	i);
	if(ret	<	0){
		return	ret;
	}
	c_int*		s	=	new	c_int();
	if(!s){
		stack->throw_exception(EXCP_CONSTRUCT_FAIL);
		return	en_cnstrct_fail;
	}
	s->m_val	=	ts->m_val	+	i->m_val;

	assert(ir);
	ir->set_ent(s);
	stack->set_ireg(s->m_val);
	return	ret;
}


s32			c_int::print(c_io_base* io,c_stack* stack)
{
	s8	buf[32];
	sprintf(buf,LLI_F,m_val);
	io->write(buf,	strlen(buf));
	return	en_sucess;
}

c_int&	c_int::operator-=	(const	c_int&	r)
{
	m_val	-=	r.m_val;
	return	*this;
}
c_int	operator-(const	c_int&	l,	const	c_int&	r)
{
	c_int	ret;
	ret.m_val	=	l.m_val	-	r.m_val;
	return	ret;
}

s32		c_int::i_sube(c_stack*	stack)
{
	s32			ret	=	en_sucess;
	c_int*		ts	=	NULL;
	c_int*		i	=	NULL;
	ret	=	i_stack_get(stack,	ts,	i);
	if(ret	<	0){
		return	ret;
	}
	ts->m_val	-=	i->m_val;
	stack->set_ireg(ts->m_val);
	return	ret;
}
s32		c_int::i_sub(c_stack*	stack)
{
	s32			ret	=	en_sucess;
	c_int*		ts	=	NULL;
	c_int*		i	=	NULL;
	ret	=	i_stack_get(stack,	ts,	i);
	if(ret	<	0){
		return	ret;
	}
	c_int*		s	=	new	c_int();
	if(!s){
		stack->throw_exception(EXCP_CONSTRUCT_FAIL);
		return	en_cnstrct_fail;
	}
	s->m_val	=	ts->m_val	-	i->m_val;
	c_object*	ir	=	stack->get_ret_reg();
	assert(ir);
	ir->set_ent(s);
	stack->set_ireg(s->m_val);
	return	ret;
}
c_int&	c_int::operator*=	(const	c_int&	r)
{
	m_val	*=	r.m_val;
	return	*this;
}

c_int	operator*(const	c_int&	l,	const	c_int&	r)
{
	c_int	ret;
	ret.m_val	=	l.m_val	*	r.m_val;
	return	ret;
}

s32		c_int::i_mute(c_stack*	stack)
{
	int			ret	=	en_sucess;
	c_int*		ts	=	NULL;
	c_int*		i	=	NULL;
	ret	=	i_stack_get(stack,	ts,	i);
	if(ret	<	0){
		return	ret;
	}
	ts->m_val	*=	i->m_val;
	stack->set_ireg(ts->m_val);
	return	ret;
}

s32		c_int::i_mut(c_stack*	stack)
{
	s32			ret	=	en_sucess;
	c_int*		ts	=	NULL;
	c_int*		i	=	NULL;
	ret	=	i_stack_get(stack,	ts,	i);
	if(ret	<	0){
		return	ret;
	}
	c_int*		s	=	new	c_int();
	if(!s){
		stack->throw_exception(EXCP_CONSTRUCT_FAIL);
		return	en_cnstrct_fail;
	}
	s->m_val	=	ts->m_val	*	i->m_val;
	c_object*	ir	=	stack->get_ret_reg();
	assert(ir);
	ir->set_ent(s);
	stack->set_ireg(s->m_val);
	return	ret;
}

c_int&	c_int::operator/=	(const	c_int&	r)
{
	m_val	/=	r.m_val;
	return	*this;
}

c_int	operator/(const	c_int&	l,	const	c_int&	r)
{
	c_int	ret;
	ret.m_val	=	l.m_val	/	r.m_val;
	return	ret;
}

s32		c_int::i_dive(c_stack*	stack)
{
	s32			ret	=	en_sucess;
	c_int*		ts	=	NULL;
	c_int*		i	=	NULL;
	ret	=	i_stack_get(stack,	ts,	i);
	if(ret	<	0){
		return	ret;
	}
	if(!i->m_val){
		stack->throw_exception(EXCP_DIV_ZERO);
		return	en_div_zero;
	}
	ts->m_val	/=	i->m_val;
	stack->set_ireg(ts->m_val);
	return	ret;
}

s32		c_int::i_div(c_stack*	stack)
{
	int			ret	=	en_sucess;
	c_int*		ts	=	NULL;
	c_int*		i	=	NULL;
	ret	=	i_stack_get(stack,	ts,	i);
	if(ret	<	0){
		return	ret;
	}
	c_int*		s	=	new	c_int();
	if(!s){
		stack->throw_exception(EXCP_CONSTRUCT_FAIL);
		return	en_cnstrct_fail;
	}
	if(!i->m_val){
		stack->throw_exception(EXCP_DIV_ZERO);
		return	en_div_zero;
	}
	s->m_val	=	ts->m_val	/	i->m_val;
	c_object*	ir	=	stack->get_ret_reg();
	assert(ir);
	ir->set_ent(s);
	stack->set_ireg(s->m_val);
	return	ret;
}

c_int&	c_int::operator%=	(const	c_int&	r)
{
	m_val	%=	r.m_val;
	return	*this;
}

c_int	operator%(const	c_int&	l,	const	c_int&	r)
{
	c_int	ret;
	ret.m_val	=	l.m_val	%	r.m_val;
	return	ret;
}

s32		c_int::i_mode(c_stack*	stack)
{
	s32			ret	=	en_sucess;
	c_int*		ts	=	NULL;
	c_int*		i	=	NULL;
	ret	=	i_stack_get(stack,	ts,	i);
	if(ret	<	0){
		return	ret;
	}
	if(!i->m_val){
		stack->throw_exception(EXCP_DIV_ZERO);
		return	en_div_zero;
	}
	ts->m_val	%=	i->m_val;
	stack->set_ireg(ts->m_val);
	return	ret;
}

s32		c_int::recycle(c_stack*	stack)
{
	if(stack){
		stack->deallocate(this,	sizeof(c_int));
	}else{
		delete	this;
	}
	return	en_sucess;
}

s32		c_int::i_mod(c_stack*	stack)
{
	s32			ret	=	en_sucess;
	c_int*		ts	=	NULL;
	c_int*		i	=	NULL;
	ret	=	i_stack_get(stack,	ts,	i);
	if(ret	<	0){
		return	ret;
	}
	c_int*		s	=	new	c_int();
	if(!s){
		stack->throw_exception(EXCP_CONSTRUCT_FAIL);
		return	en_cnstrct_fail;
	}
	if(!i->m_val){
		stack->throw_exception(EXCP_DIV_ZERO);
		return	en_div_zero;
	}
	s->m_val	=	ts->m_val	%	i->m_val;
	c_object*	ir	=	stack->get_ret_reg();
	assert(ir);
	ir->set_ent(s);
	stack->set_ireg(s->m_val);
	return	ret;
}

s32		c_int::i_neq(c_stack*	stack)
{
	s32			ret	=	en_sucess;
	c_int*		ts	=	NULL;
	c_int*		i	=	NULL;
	ret	=	i_stack_get(stack,	ts,	i);
	if(ret	<	0){
		return	ret;
	}
	if(!i->m_val){
		stack->throw_exception(EXCP_DIV_ZERO);
		return	en_div_zero;
	}
	stack->set_bflag(ts->m_val	!=	i->m_val);
	return	ret;
}
s32		c_int::i_eql(c_stack*	stack)
{
	s32			ret	=	en_sucess;
	c_int*		ts	=	NULL;
	c_int*		i	=	NULL;
	ret	=	i_stack_get(stack,	ts,	i);
	if(ret	<	0){
		return	ret;
	}
	if(!i->m_val){
		stack->throw_exception(EXCP_DIV_ZERO);
		return	en_div_zero;
	}
	stack->set_bflag(ts->m_val	==	i->m_val);
	return	ret;
}
s32		c_int::i_lag(c_stack*	stack)
{
	s32			ret	=	en_sucess;
	c_int*		ts	=	NULL;
	c_int*		i	=	NULL;
	ret	=	i_stack_get(stack,	ts,	i);
	if(ret	<	0){
		return	ret;
	}
	if(!i->m_val){
		stack->throw_exception(EXCP_DIV_ZERO);
		return	en_div_zero;
	}
	stack->set_bflag(ts->m_val	==	i->m_val);
	return	ret;
}
s32		c_int::i_sml(c_stack*	stack)
{
	s32			ret	=	en_sucess;
	c_int*		ts	=	NULL;
	c_int*		i	=	NULL;
	ret	=	i_stack_get(stack,	ts,	i);
	if(ret	<	0){
		return	ret;
	}
	if(!i->m_val){
		stack->throw_exception(EXCP_DIV_ZERO);
		return	en_div_zero;
	}
	stack->set_bflag(ts->m_val	<	i->m_val);
	return	ret;
}
s32		c_int::i_lge(c_stack*	stack)
{
	s32			ret	=	en_sucess;
	c_int*		ts	=	NULL;
	c_int*		i	=	NULL;
	ret	=	i_stack_get(stack,	ts,	i);
	if(ret	<	0){
		return	ret;
	}
	if(!i->m_val){
		stack->throw_exception(EXCP_DIV_ZERO);
		return	en_div_zero;
	}
	stack->set_bflag(ts->m_val	>=	i->m_val);
	return	ret;
}
s32		c_int::i_sme(c_stack*	stack)
{
	s32			ret	=	en_sucess;
	c_int*		ts	=	NULL;
	c_int*		i	=	NULL;
	ret	=	i_stack_get(stack,	ts,	i);
	if(ret	<	0){
		return	ret;
	}
	if(!i->m_val){
		stack->throw_exception(EXCP_DIV_ZERO);
		return	en_div_zero;
	}
	stack->set_bflag(ts->m_val	<=	i->m_val);
	return	ret;
}

s32		c_int::i_hash(c_stack*	stack)
{
	c_int*	ts	=	NULL;
	i_stack_get(stack,	ts);
	stack->set_ireg(ts->m_val);
	return	en_sucess;
}

s32		c_int::i_inc(c_stack*	stack)
{
	c_int*	ts	=	NULL;
	i_stack_get(stack,	ts);
	++ts->m_val;
	stack->set_ireg(ts->m_val);
	return	en_sucess;
}
s32		c_int::i_dec(c_stack*	stack)
{
	c_int*	ts	=	NULL;
	i_stack_get(stack,	ts);
	--ts->m_val;
	stack->set_ireg(ts->m_val);
	return	en_sucess;
}

void*	c_int::operator new(size_t)
{
	return	be::alloc::allocate(sizeof(c_int));
}
void	c_int::operator delete(void* ptr,size_t)
{
	be::alloc::deallocate(ptr,sizeof(c_int));
}




CD_NAMESPACE_END